<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <link rel="shortcut icon" type="image/ico" href="favicon.ico" />
  <title>SlickGrid example 10: Async post render</title>
  <link rel="stylesheet" href="../slick.grid.css" type="text/css"/>
  <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.11.3.custom.css" type="text/css"/>
  <link rel="stylesheet" href="examples.css" type="text/css"/>
  <style>
    .cell-title {
      font-weight: bold;
    }

    .cell-effort-driven {
      text-align: center;
    }

    .description * {
      font-size: 11pt;
    }
  </style>
</head>
<body>
<div style="width:600px;float:left;">
  <div class="grid-header" style="width:100%">
    <label>Scores:</label>
  </div>
  <div id="myGrid" style="width:100%;height:500px;"></div>
</div>

<div style="margin-left:650px;margin-top:40px;" class="description">
  <h2>Demonstrates:</h2>

  <p>
    This page extends async background post-rendering to accept a cleanup function.<br/>
    The column <u>asyncPostRender</u> property sets a function to manipulate the cell DOM node directly.<br/>
    The new column <u>asyncPostRenderCleanup</u> property sets a function to properly clean up the data
      and/or events created in the render phase.<br/>
    Post processed nodes are detached from the DOM rather then deleted, and the detached node is queued
    for cleanup using the same time-delayed technique that is used for rendering.<br/>
    It is still important to make sure that post-processing and cleanup of rows doesn't take too long.
    SlickGrid will figure out what and when needs to be updated for you.
  </p>
  <p>
    The example below is a list of 500 rows with a title and 5 integer cells followed by graphical representation of
    these integers.
    The graph is drawn using a CANVAS element in the background.
    The grid is editable, so you can edit the numbers and see the changes reflected (almost) immediately in the graph.
    The graph cell behaves just like an ordinary cell and can be resized/reordered.<br/>
    The more heavyweight jQuery Sparklines 2.x is used in this example because it requires explicit jQuery cleanup and
    will leak memory if the DOM node is instead directly deleted.<br/>
    This example page logs cleanup and render operations to the console to allow easy confirmation of the order of
    operations, but this is not recommended except in the case of debugging.<br/>
    <br/>
    Post-render cleanup must be enabled using the option <u>enableAsyncPostRenderCleanup</u>. If post-rendering is
    enabled with the <u>enableAsyncPostRender</u> option, but cleanup is not enabled, then SlickGrid will directly
    remove DOM nodes. This way is more efficient where post-rendered nodes do not require explicit resource cleanup.
  </p>
    <h2>View Source:</h2>
    <ul>
        <li><A href="https://github.com/6pac/SlickGrid/blob/master/examples/example10-async-post-render.html" target="_sourcewindow"> View the source for this example on Github</a></li>
    </ul>
</div>

<script src="../lib/firebugx.js"></script>

<script src="../lib/jquery-1.11.2.min.js"></script>
<script src="../lib/jquery-ui-1.11.3.min.js"></script>
<script src="../lib/jquery.event.drag-2.3.0.js"></script>
<script src="../lib/jquery.sparkline-2-1-2.min.js"></script>

<script src="../slick.core.js"></script>
<script src="../slick.editors.js"></script>
<script src="../slick.grid.js"></script>

<script>
  function requiredFieldValidator(value) {
    if (value == null || value == undefined || !value.length) {
      return {valid: false, msg: "This is a required field"};
    } else {
      return {valid: true, msg: null};
    }
  }

  function waitingFormatter(value) {
    return "wait...";
  }

  function renderSparkline(cellNode, rowIdx, dataContext, colDef, cleanupBeforeRender) {
      // the final bool parameter, 'cleanupBeforeRender', indicates the the cell is being
      // re-rendered (ie. has already been rendered) and prior activity should be cleaned
      // up before rendering.
      // In this example we call .empty() regardless, so we can ignore this flag, but
      // if for example a jQueryUI element was being created, then the existing element's
      // .destroy() method should be called prior to creating the new element if this
      // flag is true.

      var vals = [
          dataContext["n1"],
          dataContext["n2"],
          dataContext["n3"],
          dataContext["n4"],
          dataContext["n5"]
      ];

      // Sparkline 2's new ability to cache hidden nodes can cause memory leaks if not used
      // correctly. Slickgrid does not use it, so turn it off with 'disableHiddenCheck'.
      $(cellNode).empty().sparkline(vals, {width: "100%", disableHiddenCheck: true});

      console.log('rendered: R' + rowIdx + '-C' + colDef.name + (cleanupBeforeRender ? ' (re-render)' : ''));
  }

  // this cleanup function must clean up resources and remove the node
  function cleanupSparkline(cellNode, rowIdx, colDef) {
      $(cellNode).remove();

      console.log('cleaned: R' + rowIdx + '-C' + colDef.name);
  }

  var grid;
  var data = [];
  var columns = [
    {id: "title", name: "Title", field: "title", sortable: false, width: 120, cssClass: "cell-title"},
    {id: "n1", name: "1", field: "n1", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator},
    {id: "n2", name: "2", field: "n2", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator},
    {id: "n3", name: "3", field: "n3", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator},
    {id: "n4", name: "4", field: "n4", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator},
    {id: "n5", name: "5", field: "n5", sortable: false, editor: Slick.Editors.Integer, width: 40, validator: requiredFieldValidator},
    {id: "chart", name: "Chart", sortable: false, width: 60, formatter: waitingFormatter, rerenderOnResize: true,
        asyncPostRender: renderSparkline, asyncPostRenderCleanup: cleanupSparkline}
  ];

  var options = {
    editable: true,
    enableAddRow: false,
    enableCellNavigation: true,
    asyncEditorLoading: false,
    enableAsyncPostRender: true,
    enableAsyncPostRenderCleanup: true
  };


  $(function () {
    for (var i = 0; i < 500; i++) {
      var d = (data[i] = {});

      d["title"] = "Record " + i;
      d["n1"] = Math.round(Math.random() * 10);
      d["n2"] = Math.round(Math.random() * 10);
      d["n3"] = Math.round(Math.random() * 10);
      d["n4"] = Math.round(Math.random() * 10);
      d["n5"] = Math.round(Math.random() * 10);
    }

    grid = new Slick.Grid("#myGrid", data, columns, options);
  })
</script>
</body>
</html>
